package com.hzhr.iot.collect.protocol.parser;

import com.hzhr.iot.collect.constant.MessageFieldKeyEnum;
import com.hzhr.iot.collect.constant.MessageFieldParsingModeEnum;
import com.hzhr.iot.collect.constant.RequestResponseFlagEnum;
import com.hzhr.iot.collect.constant.UpDownEnum;
import com.hzhr.iot.collect.constant.entity.*;
import com.hzhr.iot.collect.constant.entity.constant.*;
import com.hzhr.iot.collect.protocol.checker.Checker;
import com.hzhr.iot.collect.protocol.decipher.Decipher;
import com.hzhr.iot.collect.protocol.encipher.Encipher;
import com.hzhr.iot.collect.util.MathUtil;
import com.hzhr.iot.collect.util.StrUtil;
import com.hzhr.iot.core.util.HzhrTypeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

@Component
public class Parser1 implements Parser {
    @Autowired
    Decipher decipher1;
    @Autowired
    Encipher encipher1;
    @Autowired
    Checker checker1;

    @Override
    public Decipher getDecipher() {
        return decipher1;
    }

    @Override
    public Encipher getEncipher() {
        return encipher1;
    }

    @Override
    public Checker getChecker() {
        return checker1;
    }

    @Override
    public Map<MessageFieldKeyEnum, Object> parsing(String message, int protocolId, String deviceId, UpDownEnum upDownFlag) throws Exception {
        Decipher decipher = getDecipher();
        Checker checker = getChecker();

        //解密
        if (decipher != null) {
            message = decipher.decipher(message, protocolId, deviceId, upDownFlag);
        }

        //校验
        if (checker != null) {
            boolean checkResult = checker.check(message, protocolId);
            if (!checkResult) {
                throw new Exception("CRC校验错误");
            }
        }

        MessagetmpEntity messagetmpEntity = MessagetmpEntityConstant.getMessagetmpEntityByProtocolId(protocolId);

        Map<MessageFieldKeyEnum, Object> parsedMessage = new HashMap<>();
        //解析起始码
        Integer startCodeFieldId = messagetmpEntity.getStartcodefieldId();
        MessagefieldEntity startCodeFieldEntity = MessagefieldEntityConstant.MAP.get(startCodeFieldId);
        parsedMessage.putAll(parsingMessageField(messagetmpEntity,  message, startCodeFieldEntity, null));
        //解析结束码
        Integer endCodeFieldId = messagetmpEntity.getEndcodefieldId();
        MessagefieldEntity endCodeFieldEntity = MessagefieldEntityConstant.MAP.get(endCodeFieldId);
        parsedMessage.putAll(parsingMessageField(messagetmpEntity, message, endCodeFieldEntity, null));
        //解析加密字节
        Integer encryptedByteFieldId = messagetmpEntity.getEncryptedbytefieldId();
        MessagefieldEntity encryptedByteFieldEntity = MessagefieldEntityConstant.MAP.get(encryptedByteFieldId);
        if (encryptedByteFieldEntity != null) {
            parsedMessage.putAll(parsingMessageField(messagetmpEntity, message, encryptedByteFieldEntity, null));
        }
        //解析校验码
        Integer crcFieldId = messagetmpEntity.getCrcfieldId();
        MessagefieldEntity crcFieldEntity = MessagefieldEntityConstant.MAP.get(crcFieldId);
        parsedMessage.putAll(parsingMessageField(messagetmpEntity, message, crcFieldEntity, null));
        //解析报文头
        Integer messageHeadTempId = messagetmpEntity.getMessageheadtempId();
        MessageheadtmpEntity messageheadtmpEntity = MessageheadtmpEntityConstant.MAP.get(messageHeadTempId);
        Integer messageHeadStartIndex = messageheadtmpEntity.getStartindex() * 2;
        Integer messageHeadSize = messageheadtmpEntity.getSize() * 2;
        String oriMessageHead = StrUtil.substring(message, messageHeadStartIndex, messageHeadStartIndex + messageHeadSize);
        parsedMessage.putAll(parsingMessageHead(messagetmpEntity, messageheadtmpEntity, oriMessageHead));
        if (parsedMessage.get(MessageFieldKeyEnum.MESSAGE_SIZE) != null) {
            Integer messageSize = Integer.parseInt(parsedMessage.get(MessageFieldKeyEnum.MESSAGE_SIZE).toString());
            if (messageSize != message.length() / 2) {
                return parsedMessage;
            }
        }
        //解析数据域长度
        Integer dataAreaSizeFieldId = messagetmpEntity.getDataareasizefieldId();
        MessagefieldEntity dataAreaSizeFieldEntity = MessagefieldEntityConstant.MAP.get(dataAreaSizeFieldId);
        if (dataAreaSizeFieldEntity != null) {
            parsedMessage.putAll(parsingMessageField(messagetmpEntity, message, dataAreaSizeFieldEntity, null));
        }
        //解析数据域
        String functionCode = parsedMessage.get(MessageFieldKeyEnum.FUNCTION_CODE).toString();
        FunctionEntity functionEntity = FunctionEntityConstant.getFunctionEntityByProtocolIdAndFunctionCode(protocolId, functionCode);
        Integer dataAreaTmpId = functionEntity.getDataareatmpId();
        DataareatmpEntity dataareatmpEntity = DataareatmpEntityConstant.MAP.get(dataAreaTmpId);
        String dataAreaSizeStr = HzhrTypeUtil.object2string(parsedMessage.get(MessageFieldKeyEnum.DATA_AREA_SIZE));
        int dataAreaSize = 0;
        if (StringUtils.isEmpty(dataAreaSizeStr)) {
            int messageSize = Integer.parseInt(parsedMessage.get(MessageFieldKeyEnum.MESSAGE_SIZE).toString()) * 2;
            int startCodeSize = parsedMessage.get(MessageFieldKeyEnum.START_CODE).toString().length();
            int endCodeSize = parsedMessage.get(MessageFieldKeyEnum.END_CODE).toString().length();
            dataAreaSize = messageSize - messageHeadSize - startCodeSize - endCodeSize;
        } else {
            dataAreaSize = Integer.parseInt(dataAreaSizeStr) * 2;
        }
        Integer dataAreaStartIndex = dataareatmpEntity.getStartindex() * 2;
        String oriDataArea = StrUtil.substring(message, dataAreaStartIndex, dataAreaStartIndex + dataAreaSize);

        String reqRespFlagStr = HzhrTypeUtil.object2string(parsedMessage.get(MessageFieldKeyEnum.REQ_RESP_FLAG));
        String controlCodeStr = HzhrTypeUtil.object2string(parsedMessage.get(MessageFieldKeyEnum.CONTROL_CODE));
        RequestResponseFlagEnum requestResponseFlag = null;
        if (!StringUtils.isEmpty(reqRespFlagStr)) {
            requestResponseFlag = RequestResponseFlagEnum.getEnumByIdForMessage(Integer.parseInt(reqRespFlagStr));
        } else if (!StringUtils.isEmpty(controlCodeStr)) {
            String controlCodeBin = StrUtil.decimal2binary(Integer.parseInt(controlCodeStr));
            String starteFlag = controlCodeBin.charAt(0) + ""; //通信发启标识：0 服务器端发启 1 设备端发启
            String transFlag = controlCodeBin.charAt(1) + ""; //传输方向标识：0 下行 1 上行

            if (starteFlag.equals(transFlag)) {
                requestResponseFlag = RequestResponseFlagEnum.REQ;
            } else {
                requestResponseFlag = RequestResponseFlagEnum.RESP;
            }
        }

        if (requestResponseFlag != null) {
            parsedMessage.putAll(parsingDataArea(messagetmpEntity, dataareatmpEntity, oriDataArea, requestResponseFlag));
        }
        return parsedMessage;
    }

    @Override
    public String inverselyParsing(Map<MessageFieldKeyEnum, Object> messageObj, int protocolId, String deviceId, UpDownEnum upDownFlag) throws Exception {
        Encipher encipher = getEncipher();

        StringBuilder messageSb = new StringBuilder();
        SortedMap<Integer, String> messageMap = new TreeMap<>();

        MessagetmpEntity messagetmpEntity = MessagetmpEntityConstant.getMessagetmpEntityByProtocolId(protocolId);

        //反解析起始码
        Integer startCodeFieldId = messagetmpEntity.getStartcodefieldId();
        messageMap.putAll(inverselyParsingMessageField(messagetmpEntity, messageObj, startCodeFieldId, null));

        //反解析报文头
        Integer messageHeadTempId = messagetmpEntity.getMessageheadtempId();
        MessageheadtmpEntity messageheadtmpEntity = MessageheadtmpEntityConstant.MAP.get(messageHeadTempId);
        String messageHead = inverselyParsingMessageHead(messagetmpEntity, messageheadtmpEntity, messageObj);
        Integer messageHeadStartIndex = messageheadtmpEntity.getStartindex();
        messageMap.put(messageHeadStartIndex, messageHead);

        //反解析数据域长度
        Integer dataAreaSizeFieldId = messagetmpEntity.getDataareasizefieldId();
        messageMap.putAll(inverselyParsingMessageField(messagetmpEntity, messageObj, dataAreaSizeFieldId, null));

        //反解析数据域
        String functionCode = messageObj.get(MessageFieldKeyEnum.FUNCTION_CODE).toString();
        FunctionEntity functionEntity = FunctionEntityConstant.getFunctionEntityByProtocolIdAndFunctionCode(protocolId, functionCode);
        Integer dataAreaTmpId = functionEntity.getDataareatmpId();
        DataareatmpEntity dataareatmpEntity = DataareatmpEntityConstant.MAP.get(dataAreaTmpId);

        String reqRespFlagStr = HzhrTypeUtil.object2string(messageObj.get(MessageFieldKeyEnum.REQ_RESP_FLAG));
        String controlCodeStr = HzhrTypeUtil.object2string(messageObj.get(MessageFieldKeyEnum.CONTROL_CODE));
        RequestResponseFlagEnum requestResponseFlag = null;
        if (!StringUtils.isEmpty(reqRespFlagStr)) {
            requestResponseFlag = RequestResponseFlagEnum.getEnumByIdForMessage(Integer.parseInt(reqRespFlagStr));
        } else if (!StringUtils.isEmpty(controlCodeStr)) {
            String controlCodeBin = StrUtil.decimal2binary(Integer.parseInt(controlCodeStr));
            String starteFlag = controlCodeBin.charAt(0) + ""; //通信发启标识：0 服务器端发启 1 设备端发启
            String transFlag = controlCodeBin.charAt(1) + ""; //传输方向标识：0 下行 1 上行

            if (starteFlag.equals(transFlag)) {
                requestResponseFlag = RequestResponseFlagEnum.REQ;
            } else {
                requestResponseFlag = RequestResponseFlagEnum.RESP;
            }
        }

        String dataArea = inverselyParsingDataArea(messagetmpEntity, dataareatmpEntity, messageObj, requestResponseFlag);
        messageMap.put(dataareatmpEntity.getStartindex(), dataArea);

        //反解析加密字节
        Integer encryptedByteFieldId =messagetmpEntity.getEncryptedbytefieldId();
        messageMap.putAll(inverselyParsingMessageField(messagetmpEntity, messageObj, encryptedByteFieldId, null));

        //反解析校验码
        Integer crcFieldId = messagetmpEntity.getCrcfieldId();
        messageMap.putAll(inverselyParsingMessageField(messagetmpEntity, messageObj, crcFieldId, null));

        //反解析结束码
        Integer endCodeFieldId = messagetmpEntity.getEndcodefieldId();
        messageMap.putAll(inverselyParsingMessageField(messagetmpEntity, messageObj, endCodeFieldId, null));

        for (Map.Entry<Integer, String> entry : messageMap.entrySet()) {
            messageSb.append(entry.getValue());
        }

        String message = messageSb.toString();
        int messageLength = message.length();//反解析后的报文长度

        //生成加密字节
        String encryptedByte = null;//加密字节
        if (encryptedByteFieldId != null) {
            String generateEncryptedMessage = StrUtil.substring(message, 0, message.length() - 8);
            int sum = 0;//校验和
            for (int i = 0; i < generateEncryptedMessage.length(); i += 2) {
                sum += new Integer(StrUtil.hexStr2decStr(StrUtil.substring(generateEncryptedMessage, i, i + 2)));
            }
            String sumStr = Integer.toHexString(sum);
            encryptedByte = StrUtil.getLowerByte(sumStr);//取低八位
            message = StrUtil.substring(message, 0, messageLength - 4 * 2) + encryptedByte + StrUtil.substring(message,messageLength - 6);

        }

        //生成校验码
        String generateCrcMesssage = StrUtil.substring(message,0, message.length() - 6);
        String crc = StrUtil.reverseUpperAndLowerByte(StrUtil.getCrc16(StrUtil.hexStr2byte(generateCrcMesssage)));
        message = StrUtil.substring(message,0, messageLength - 3 * 2) + crc + StrUtil.substring(message,messageLength - 2);

        //加密
        if (encryptedByte != null) {
            message = encipher.encrypt(message, protocolId, deviceId, upDownFlag);
        }

        return message;
    }


    private List<String> ignoredFieldNameForParsingMessageHead = Arrays.asList("id", "size", "startindex", "fieldsizesum", "reqfieldsizesum", "respfieldsizesum");
    private Map<MessageFieldKeyEnum, Object> parsingMessageField(MessagetmpEntity messagetmpEntity, DataareatmpEntity dataareatmpEntity, String message, MessagefieldEntity fieldEntity, RequestResponseFlagEnum requestResponseFlagEnum) {
        Map<MessageFieldKeyEnum, Object> fieldMap = new HashMap<>();

        if (requestResponseFlagEnum != null && requestResponseFlagEnum.getId() != fieldEntity.getReqrespflag()) {
            return fieldMap;
        }
        Integer fieldStartIndex = (fieldEntity.getStartindex() * 2 + message.length()) % message.length();
        Integer fieldSize = fieldEntity.getSize() * 2;

        if (dataareatmpEntity != null && dataareatmpEntity.getDetailconutfieldIdList() != null && dataareatmpEntity.getDetailconutfieldIdList().size() > 0) {//数据域多条目解析
            Integer realFieldStartIndex = fieldStartIndex;
            Integer addCount = 0;
            List<Integer> detailcountfieldIdList = dataareatmpEntity.getDetailconutfieldIdList();
            for (int i = 0; i < detailcountfieldIdList.size(); i++) {
                realFieldStartIndex += addCount;

                Integer detailcountfieldId = detailcountfieldIdList.get(i);
                MessagefieldEntity detailcountfieldEntity = MessagefieldEntityConstant.MAP.get(detailcountfieldId);
                Integer detailcountfieldStartIndex = (detailcountfieldEntity.getStartindex() * 2 + message.length()) % message.length() + addCount;
                Integer detailcountfieldSize = detailcountfieldEntity.getSize() * 2;
                Map<MessageFieldKeyEnum, Object> detailcountfieldObj = parsingSingleMessageField(messagetmpEntity, detailcountfieldEntity, message, detailcountfieldStartIndex, detailcountfieldSize);

                MessageFieldKeyEnum messageFieldKeyEnum = MessageFieldKeyEnum.getEnumByid(detailcountfieldEntity.getTmpId());
                Integer detailcount = Integer.parseInt(detailcountfieldObj.get(messageFieldKeyEnum).toString());
                Integer subareastartindex = detailcountfieldEntity.getSubareastartindex();
                Integer subareasize = detailcountfieldEntity.getSubareasize();

                Integer oriFieldStartIndex = fieldEntity.getStartindex();
                if (oriFieldStartIndex < subareastartindex) {
                    return parsingSingleMessageField(messagetmpEntity, fieldEntity, message, realFieldStartIndex, fieldSize);
                } else if (oriFieldStartIndex < subareastartindex + subareasize) {
                    List<String> parsedField = new ArrayList<>();
                    for (int j = 0; j < detailcount; j++) {
                        String oriField = StrUtil.substringBySize(message, realFieldStartIndex, fieldSize);

                        int reverseMode = messagetmpEntity.getReverseMode();
                        if (reverseMode == 0) {//全部取反
                            oriField = StrUtil.reverseUpperAndLowerByte(oriField);//高低位取反
                        } else if (reverseMode == 2) {//hex取反
                            if (MessageFieldParsingModeEnum.HEX.getId() == fieldEntity.getParsingmode()) {
                                oriField = StrUtil.reverseUpperAndLowerByte(oriField);//高低位取反
                            }
                        }

                        if (oriField == null) {
                            return fieldMap;
                        }
                        //				if (!StringUtils.isEmpty(fieldEntity.getFixedvalue())) {//有固定值
                        //					if ( !fieldEntity.getFixedvalue().equals(oriField) ) {
                        //						return fieldMap;
                        //					}
                        //				}

                        Integer fieldParsingModeId = fieldEntity.getParsingmode();
                        String parsedFieldItem = null;
                        if (MessageFieldParsingModeEnum.HEX.getId() == fieldParsingModeId) {
                            parsedFieldItem = StrUtil.hexStr2decStr(oriField);
                            if (parsedFieldItem == null) continue;
                            if (fieldEntity.getUnit() != null) {
                                Float unit = fieldEntity.getUnit();
                                BigDecimal unitB = new BigDecimal(unit.toString());
                                BigDecimal parsedFieldItemB = new BigDecimal(parsedFieldItem);
                                if (MathUtil.isInt(unit)) {//unit为整数
                                    parsedFieldItem = parsedFieldItemB.multiply(unitB).toString();//乘以单位
                                } else {
                                    parsedFieldItem = parsedFieldItemB.multiply(unitB).toString();//乘以单位
                                }
                            }
                        } else if (MessageFieldParsingModeEnum.BCD.getId() == fieldParsingModeId) {
                            parsedFieldItem = StrUtil.bcd2decStr(oriField);
                            if (parsedFieldItem == null) continue;
                            if (fieldEntity.getUnit() != null) {
                                Float unit = fieldEntity.getUnit();
                                BigDecimal unitB = new BigDecimal(unit.toString());
                                BigDecimal parsedFieldItemB = new BigDecimal(parsedFieldItem);
                                if (MathUtil.isInt(unit)) {//unit为整数
                                    parsedFieldItem = parsedFieldItemB.multiply(unitB).toString();//乘以单位
                                } else {
                                    parsedFieldItem = parsedFieldItemB.multiply(unitB).toString();//乘以单位
                                }
                            }
                        } else if (MessageFieldParsingModeEnum.CHAR.getId() == fieldParsingModeId) {
                            parsedFieldItem = StrUtil.char2str(oriField);
                            if (parsedFieldItem == null) continue;
                        } else if (MessageFieldParsingModeEnum.SIGNED_HEX.getId() == fieldParsingModeId) {
                            parsedFieldItem = StrUtil.signedHexStr2decStr(oriField);
                            if (parsedFieldItem == null) continue;
                            if (fieldEntity.getUnit() != null) {
                                Float unit = fieldEntity.getUnit();
                                BigDecimal unitB = new BigDecimal(unit.toString());
                                BigDecimal parsedFieldItemB = new BigDecimal(parsedFieldItem);
                                if (MathUtil.isInt(unit)) {//unit为整数
                                    parsedFieldItem = parsedFieldItemB.multiply(unitB).toString();//乘以单位
                                } else {
                                    parsedFieldItem = parsedFieldItemB.multiply(unitB).toString();//乘以单位
                                }
                            }
                        }

                        parsedField.add(parsedFieldItem);
                        realFieldStartIndex = realFieldStartIndex + subareasize * 2;
                    }
                    Integer tmpId = fieldEntity.getTmpId();
                    MessagefieldtmpEntity messagefieldtmpEntity = MessagefieldtmpEntityConstant.MAP.get(tmpId);
                    String fieldKey = messagefieldtmpEntity.getFieldkeyname();
                    fieldMap.put(MessageFieldKeyEnum.getEnumByEnumName(fieldKey), parsedField);
                    return fieldMap;
                } else {
                    addCount += detailcount * subareasize;
                }
            }
            return parsingSingleMessageField(messagetmpEntity, fieldEntity, message, realFieldStartIndex, fieldSize);
        } else {//单条目解析
            return parsingSingleMessageField(messagetmpEntity, fieldEntity, message, fieldStartIndex, fieldSize);
        }
    }
    private Map<MessageFieldKeyEnum, Object> parsingMessageField(MessagetmpEntity messagetmpEntity, String message, MessagefieldEntity messagefieldEntity, RequestResponseFlagEnum requestResponseFlagEnum) {
        return parsingMessageField(messagetmpEntity, null, message, messagefieldEntity, requestResponseFlagEnum	);
    }
    private Map<MessageFieldKeyEnum, Object> parsingSingleMessageField(MessagetmpEntity messagetmpEntity, MessagefieldEntity fieldEntity, String message, Integer fieldStartIndex, Integer fieldSize) {
        Map<MessageFieldKeyEnum, Object> fieldMap = new HashMap<>();

        String oriField = StrUtil.substringBySize(message, fieldStartIndex, fieldSize);
        int reverseMode = messagetmpEntity.getReverseMode();
        if (reverseMode == 0) {//全部取反
            oriField = StrUtil.reverseUpperAndLowerByte(oriField);//高低位取反
        } else if (reverseMode == 2) {//hex取反
            if (MessageFieldParsingModeEnum.HEX.getId() == fieldEntity.getParsingmode()) {
                oriField = StrUtil.reverseUpperAndLowerByte(oriField);//高低位取反
            }
        }


        if (oriField == null) {
            return fieldMap;
        }
//			if (!StringUtils.isEmpty(fieldEntity.getFixedvalue())) {//有固定值
//				if ( !fieldEntity.getFixedvalue().equals(oriField) ) {
//					return fieldMap;
//				}
//			}

        Integer fieldParsingModeId = fieldEntity.getParsingmode();
        String parsedField = null;
        if (MessageFieldParsingModeEnum.HEX.getId() == fieldParsingModeId) {
            if (fieldEntity.getTmpId() == 28) {//ip地址 需一段一段解析
                parsedField = "";
                for (int i = 0; i < 8; i += 2) {
                    String ipItem = oriField.substring(i, i + 2);
                    if (i < 6) parsedField += StrUtil.hexStr2decStr(ipItem) + ".";
                    else parsedField += StrUtil.hexStr2decStr(ipItem);
                }
            } else {
                parsedField = StrUtil.hexStr2decStr(oriField);
                if (parsedField == null) return fieldMap;
                if (fieldEntity.getUnit() != null) {
                    Float unit = fieldEntity.getUnit();
                    BigDecimal unitB = new BigDecimal(unit.toString());
                    BigDecimal parsedFieldB = new BigDecimal(parsedField);
                    if (MathUtil.isInt(unit)) {//unit为整数
                        parsedField = parsedFieldB.multiply(unitB).toString();//乘以单位
                    } else {
                        parsedField = parsedFieldB.multiply(unitB).toString();//乘以单位
                    }
                }
            }
        } else if (MessageFieldParsingModeEnum.BCD.getId() == fieldParsingModeId) {
            parsedField = StrUtil.bcd2decStr(oriField);
            if (parsedField == null) return fieldMap;
            if (fieldEntity.getUnit() != null) {
                Float unit = fieldEntity.getUnit();
                BigDecimal unitB = new BigDecimal(unit.toString());
                BigDecimal parsedFieldB = new BigDecimal(parsedField);
                if (MathUtil.isInt(unit)) {//unit为整数
                    parsedField = parsedFieldB.multiply(unitB).toString();//乘以单位
                } else {
                    parsedField = parsedFieldB.multiply(unitB).toString();//乘以单位
                }
            }
        } else if (MessageFieldParsingModeEnum.CHAR.getId() == fieldParsingModeId) {
            parsedField = StrUtil.char2str(oriField);
            if (parsedField == null) return fieldMap;
        } else if (MessageFieldParsingModeEnum.SIGNED_HEX.getId() == fieldParsingModeId) {
            parsedField = StrUtil.signedHexStr2decStr(oriField);
            if (parsedField == null) return fieldMap;
            if (fieldEntity.getUnit() != null) {
                Float unit = fieldEntity.getUnit();
                BigDecimal unitB = new BigDecimal(unit.toString());
                BigDecimal parsedFieldItemB = new BigDecimal(parsedField);
                if (MathUtil.isInt(unit)) {//unit为整数
                    parsedField = parsedFieldItemB.multiply(unitB).toString();//乘以单位
                } else {
                    parsedField = parsedFieldItemB.multiply(unitB).toString();//乘以单位
                }
            }
        }

        Integer tmpId = fieldEntity.getTmpId();
        MessagefieldtmpEntity messagefieldtmpEntity = MessagefieldtmpEntityConstant.MAP.get(tmpId);
        String fieldKey = messagefieldtmpEntity.getFieldkeyname();
        fieldMap.put(MessageFieldKeyEnum.getEnumByEnumName(fieldKey), parsedField);
        return fieldMap;
    }
    private Map<MessageFieldKeyEnum, Object> parsingMessageHead(MessagetmpEntity messagetmpEntity, MessageheadtmpEntity messageheadtmpEntity,
                                                        String messagehead) {
        Map<MessageFieldKeyEnum, Object> messageHeadMap = new HashMap<>();

        Field[] fields = messageheadtmpEntity.getClass().getDeclaredFields();
        for (Field field : fields) {//遍历报文头模板的属性
            String fieldName = field.getName();
            if (!ignoredFieldNameForParsingMessageHead.contains(fieldName)) {//根据模板解析报文头中的每一个功能字段
                try {
                    Method method = messageheadtmpEntity.getClass()
                            .getMethod("get"+StrUtil.firstCharToUppserCase(fieldName));
                    Object value = method.invoke(messageheadtmpEntity);
                    Integer fieldId = value != null ? (Integer)value : null;
                    if (fieldId != null) {
                        MessagefieldEntity messagefieldEntity = MessagefieldEntityConstant.MAP.get(fieldId);
                        Map<MessageFieldKeyEnum, Object> parsedFieldMap = parsingMessageField(messagetmpEntity, messagehead, messagefieldEntity, null);
                        messageHeadMap.putAll(parsedFieldMap);
                    }
                } catch (Exception e) {
                    throw new  RuntimeException(e);
                }
            }
        }

        return messageHeadMap;
    }
    private Map<MessageFieldKeyEnum, Object> parsingDataArea(MessagetmpEntity messagetmpEntity, DataareatmpEntity dataareatmpEntity,
                                                     String dataArea, RequestResponseFlagEnum requestResponseFlagEnum) {
        Map<MessageFieldKeyEnum, Object> parsedDataArea = new HashMap<>();

        List<Integer> fieldIdList = dataareatmpEntity.getFieldIdList();
        for (Integer fieldId : fieldIdList) {//遍历数据域模板的属性
            if (fieldId != null) {
                MessagefieldEntity messagefieldEntity = MessagefieldEntityConstant.MAP.get(fieldId);
                Map<MessageFieldKeyEnum, Object> parsedFieldMap = parsingMessageField(messagetmpEntity, dataareatmpEntity, dataArea, messagefieldEntity, requestResponseFlagEnum);
                parsedDataArea.putAll(parsedFieldMap);
            }
        }

        return parsedDataArea;
    }

    private Map<Integer, String> inverselyParsingMessageField(MessagetmpEntity messagetmpEntity, Map<MessageFieldKeyEnum, Object> parsedMessage,
                                                      Integer fieldId, RequestResponseFlagEnum requestResponseFlagEnum) {
        Map<Integer, String> result = new HashMap<>();

        if (fieldId == null) return result;
        MessagefieldEntity fieldEntity = MessagefieldEntityConstant.MAP.get(fieldId);
        if (requestResponseFlagEnum != null && requestResponseFlagEnum.getId() != fieldEntity.getReqrespflag()) {
            return result;
        }
        Integer fieldStartIndex = (10000 + fieldEntity.getStartindex()) % 10000;//为了兼容有的startIndex为负数的情况
        Integer fieldSize = fieldEntity.getSize();

        Integer tmpId = fieldEntity.getTmpId();
        MessagefieldtmpEntity messagefieldtmpEntity = MessagefieldtmpEntityConstant.MAP.get(tmpId);
        String fieldKey = messagefieldtmpEntity.getFieldkeyname();
        String oriField = null;
        if (parsedMessage.get(MessageFieldKeyEnum.getEnumByEnumName(fieldKey)) == null) {
            oriField = fieldEntity.getDefaultvalue();
        } else {
            oriField = parsedMessage.get(MessageFieldKeyEnum.getEnumByEnumName(fieldKey)).toString();
        }

        Integer fieldParsingModeId = fieldEntity.getParsingmode();
        String field = null;
        if (MessageFieldParsingModeEnum.HEX.getId() == fieldParsingModeId) {
            if (oriField.contains(".")) {
                field = "";
                String[] oriFieldSplit = oriField.split("\\.");
                for (String oriFieldSplitItem : oriFieldSplit) {
                    field += StrUtil.FillZeroForLeft(StrUtil.str2hexStr(oriFieldSplitItem), 2);
                }
            } else {
                field = StrUtil.str2hexStr(oriField);
            }
        } else if (MessageFieldParsingModeEnum.BCD.getId() == fieldParsingModeId) {
            field = StrUtil.str2bcdStr(oriField);
        }
        if (field != null) {
            field = StrUtil.FillZeroForLeft(field, fieldSize * 2);//左补零
        }

        int reverseMode = messagetmpEntity.getReverseMode();
        if (reverseMode == 0) {//全部取反
            field = StrUtil.reverseUpperAndLowerByte(field);//高低位取反
        } else if (reverseMode == 2) {//hex取反
            if (MessageFieldParsingModeEnum.HEX.getId() == fieldEntity.getParsingmode()) {
                field = StrUtil.reverseUpperAndLowerByte(field);//高低位取反
            }
        }

        result.put(fieldStartIndex, field);
        return result;
    }
    private String inverselyParsingMessageHead(MessagetmpEntity messagetmpEntity, MessageheadtmpEntity messageheadtmpEntity,
                                       Map<MessageFieldKeyEnum, Object> parsedMessagehead) {
        StringBuilder messageHeadSb = new StringBuilder();
        SortedMap<Integer, String> messageHeadMap = new TreeMap<>();

        Field[] fields = messageheadtmpEntity.getClass().getDeclaredFields();
        for (Field field : fields) {//遍历报文头模板的属性
            String fieldName = field.getName();
            if (!ignoredFieldNameForParsingMessageHead.contains(fieldName)) {//根据模板解析报文头中的每一个功能字段
                try {
                    Method method = messageheadtmpEntity.getClass()
                            .getMethod("get"+StrUtil.firstCharToUppserCase(fieldName));
                    Object value = method.invoke(messageheadtmpEntity);
                    Integer fieldId = value != null ? (Integer)value : null;
                    if (fieldId != null) {
                        messageHeadMap.putAll(inverselyParsingMessageField(messagetmpEntity, parsedMessagehead, fieldId, null));
                    }
                } catch (Exception e) {
                    throw new  RuntimeException(e);
                }
            }
        }

        for (Map.Entry<Integer, String> entry : messageHeadMap.entrySet()) {
            messageHeadSb.append(entry.getValue());
        }
        return messageHeadSb.toString();
    }
    private String inverselyParsingDataArea(MessagetmpEntity messagetmpEntity, DataareatmpEntity dataareatmpEntity,
                                    Map<MessageFieldKeyEnum, Object> parsedDataArea, RequestResponseFlagEnum requestResponseFlagEnum) {
        StringBuilder dataAreaSb = new StringBuilder();
        SortedMap<Integer, String> dataAreaMap = new TreeMap<>();

        List<Integer> fieldIdList = dataareatmpEntity.getFieldIdList();
        try {
            for (Integer fieldId : fieldIdList) {//遍历数据域模板的属性
                if (fieldId != null) {
                    dataAreaMap.putAll(inverselyParsingMessageField(messagetmpEntity, parsedDataArea, fieldId, requestResponseFlagEnum));
                }
            }
        } catch (Exception e) {
            throw new  RuntimeException(e);
        }

        for (Map.Entry<Integer, String> entry : dataAreaMap.entrySet()) {
            dataAreaSb.append(entry.getValue());
        }
        return dataAreaSb.toString();
    }
}
